package auth

import (
	"context"
	"strconv"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/common/moneyx"
	"mall/common/resultx"
	"mall/common/utils/pointy"
	"mall/service/user/model"
	"mall/service/user/rpc/internal/svc"
	userx "mall/service/user/rpc/types/user"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetCurrentUserLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewGetCurrentUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCurrentUserLogic {
	return &GetCurrentUserLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *GetCurrentUserLogic) GetCurrentUser(in *userx.GetUserReq) (*userx.CurrentUserResp, error) {
	if in.UserId == nil || *in.UserId == 0 {
		return nil, resultx.StatusError(resultx.USER_ID_REQUIRED, "")
	}

	userId := *in.UserId

	// 查询用户
	user, err := l.svcCtx.CurrentUser.FindOne(l.ctx, userId)
	if err != nil {
		return nil, err
	}

	var emailVerified uint32
	var mobileVerified uint32
	if user.UserEmailVerified > 0 {
		emailVerified = 1
	}
	if user.UserMobileVerified > 0 {
		mobileVerified = 1
	}
	resp := &userx.CurrentUserResp{
		User: &userx.TmpUserInfo{
			Id:               pointy.GetPointer(strconv.FormatUint(user.ID, 10)),
			Email:            &user.UserEmail,
			Mobile:           &user.UserMobile,
			Status:           pointy.GetPointer(uint32(user.UserStatus)),
			CreatedAt:        pointy.GetPointer(modelx.FormatTime(user.CreatedAt, "")),
			UpdatedAt:        pointy.GetPointer(modelx.FormatTime(user.UpdatedAt, "")),
			EmailVerified:    pointy.GetPointer(emailVerified),
			EmailVerifiedAt:  pointy.GetPointer(modelx.FormatNullDotTime(user.UserEmailVerifiedAt, "")),
			MobileVerified:   pointy.GetPointer(mobileVerified),
			MobileVerifiedAt: pointy.GetPointer(modelx.FormatNullDotTime(user.UserMobileVerifiedAt, "")),
			CreatedIP:        &user.CreateIP,
		},
	}

	if in.WithAuthInfo != nil && *in.WithAuthInfo > 0 {
		if in.PlatformId == nil || *in.PlatformId == 0 {
			return nil, resultx.StatusError(resultx.USER_AUTH_PARAM_INVALID, "")
		}

		filterMap := make(map[string]map[string][]any)
		switch *in.PlatformId {
		case globalkey.ThirdPartyPlatformWechatMini:
			filterMap[model.UserAuthColumns.UserID] = map[string][]any{
				"equalTo": {userId},
			}
			filterMap[model.UserAuthColumns.PlatformID] = map[string][]any{
				"equalTo": {*in.PlatformId},
			}
		}
		authList, _, err := l.svcCtx.CurrentUser.GetAuthList(l.ctx, model.M{
			"pageSize": uint64(1),
		}, -1, filterMap)
		if err != nil {
			return nil, err
		}

		if len(authList) > 0 {
			userAuth := authList[0]
			resp.UserAuth = &userx.TmpUserAuthInfo{
				UserId:     &userAuth.UserID,
				PlatformId: pointy.GetPointer(uint32(userAuth.PlatformID)),
				Openid:     &userAuth.Openid,
				Unionid:    &userAuth.Unionid,
				Nickname:   &userAuth.Nickname,
				Avatar:     &userAuth.Avatar,
				Gender:     pointy.GetPointer(uint32(userAuth.Gender)),
				Country:    &userAuth.Country,
				Province:   &userAuth.Province,
				City:       &userAuth.City,
				Language:   &userAuth.Language,
				Status:     pointy.GetPointer(uint32(userAuth.Status)),
				Authorized: pointy.GetPointer(uint32(userAuth.Status)),
				CreatedAt:  pointy.GetPointer(modelx.FormatTime(userAuth.CreatedAt, "")),
				UpdatedAt:  pointy.GetPointer(modelx.FormatTime(userAuth.UpdatedAt, "")),
				Mobile:     &userAuth.Mobile,
				Birthday:   pointy.GetPointer(modelx.FormatNullDotTime(userAuth.Birthday, "")),
				UserUUID:   pointy.GetPointer(strconv.FormatUint(userAuth.UserID, 10)),
			}
		}
	}

	if in.WithDetailInfo != nil && *in.WithDetailInfo > 0 {
		filterMap := make(map[string]map[string][]any)
		filterMap[model.UserDetailColumns.UserID] = map[string][]any{
			"equalTo": {userId},
		}
		detailList, _, err := l.svcCtx.CurrentUser.GetDetailList(l.ctx, model.M{
			"pageSize": uint64(1),
		}, -1, filterMap)
		if err != nil {
			return nil, err
		}

		if len(detailList) > 0 {
			userDetail := detailList[0]

			metumFilterMap := make(map[string]map[string][]any)
			metumFilterMap[model.UserMetumColumns.UserID] = map[string][]any{
				"equalTo": {userId},
			}
			metumFilterMap[model.UserMetumColumns.MetaKey] = map[string][]any{
				"in": {"_want_entry_count", "_own_entry_count"},
			}
			meta, _, err := l.svcCtx.CurrentUser.GetMeta(l.ctx, model.M{}, -1, metumFilterMap)
			if err != nil {
				return nil, err
			}

			var likeEntryCount *uint32
			var collectEntryCount *uint32
			if len(meta) > 0 {
				for _, v := range meta {
					if len(v.MetaKey) > 0 && v.MetaValue.Valid {
						if v.MetaKey == "_like_entry_count" {
							if i, err := strconv.ParseInt(v.MetaKey, 10, 32); err == nil && i > 0 {
								likeEntryCount = pointy.GetPointer(uint32(i))
							}
						} else if v.MetaKey == "_collect_entry_count" {
							if i, err := strconv.ParseInt(v.MetaKey, 10, 32); err == nil && i > 0 {
								collectEntryCount = pointy.GetPointer(uint32(i))
							}
						}
					}
				}
			}

			resp.UserDetail = &userx.UserDetailInfo{
				UserId:            pointy.GetPointer(strconv.FormatUint(userDetail.UserID, 10)),
				Nickname:          &userDetail.Nickname,
				Avatar:            &userDetail.Avatar,
				Gender:            pointy.GetPointer(uint32(userDetail.Gender)),
				Birthday:          pointy.GetPointer(modelx.FormatNullDotTime(userDetail.Birthday, "")),
				Country:           &userDetail.Country,
				Province:          &userDetail.Province,
				City:              &userDetail.City,
				Language:          &userDetail.Language,
				Role:              pointy.GetPointer(uint32(userDetail.Role)),
				LikeEntryCount:    likeEntryCount,
				CollectEntryCount: collectEntryCount,
			}
		}
	}

	if in.WithAccountInfo != nil && *in.WithAccountInfo > 0 {
		filterMap := make(map[string]map[string][]any)
		filterMap[model.UserAccountColumns.UserID] = map[string][]any{
			"equalTo": {userId},
		}
		accountList, _, err := l.svcCtx.CurrentUser.GetAccountList(l.ctx, model.M{
			"pageSize": uint64(1),
		}, -1, filterMap)
		if err != nil {
			return nil, err
		}

		if len(accountList) > 0 {
			userAccount := accountList[0]
			var availablePoint uint64
			if userAccount.Point > 0 && uint64(userAccount.Point) > userAccount.FrozenPoint {
				availablePoint = uint64(userAccount.Point) - userAccount.FrozenPoint
			}
			var availableBalance uint64
			if userAccount.Balance > 0 && uint64(userAccount.Balance) > userAccount.FrozenBalance {
				availableBalance = uint64(userAccount.Balance) - userAccount.FrozenBalance
			}
			resp.UserAccount = &userx.TmpUserAccountInfo{
				UserId:           pointy.GetPointer(strconv.FormatUint(userAccount.UserID, 10)),
				Point:            &userAccount.Point,
				HistoryPoint:     &userAccount.HistoryPoint,
				FrozenPoint:      &userAccount.FrozenPoint,
				AvailablePoint:   pointy.GetPointer(availablePoint),
				Balance:          pointy.GetPointer(moneyx.FormatAmount(userAccount.Balance)),
				FrozenBalance:    pointy.GetPointer(moneyx.FormatAmount(int64(userAccount.FrozenBalance))),
				AvailableBalance: pointy.GetPointer(moneyx.FormatAmount(int64(availableBalance))),
				RankId:           pointy.GetPointer(uint64(userAccount.RankID)),
				Credit:           pointy.GetPointer(userAccount.Credit),
			}
		}
	}

	if in.WithTaskStatistic != nil && *in.WithTaskStatistic > 0 {
	}

	return resp, nil
}
